package com.epoint.netty.bytebuf;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufUtil;
import org.junit.Test;

import static io.netty.buffer.ByteBufUtil.appendPrettyHexDump;
import static io.netty.util.internal.StringUtil.NEWLINE;

public class Slice {

    /**
     * 原始的效果，就一个buffer
     */
    @Test
    public void test1(){
        ByteBuf origin = ByteBufAllocator.DEFAULT.buffer(10);
        origin.writeBytes(new byte[]{1, 2, 3, 4});
        origin.readByte();
        log(origin);
    }

    /**
     * 对原buffer进行分片 【类比java里的浅拷贝】
     */
    @Test
    public void test2(){
        ByteBuf origin = ByteBufAllocator.DEFAULT.buffer(10);
        origin.writeBytes(new byte[]{1, 2, 3, 4});

        ByteBuf slice1 = origin.slice(0, 2);
        ByteBuf slice2 = origin.slice(2, 2);

        log(origin);
        log(slice1);
        log(slice2);

        // 因为slice出来的切片物理不分离，逻辑分离，所以你对原的buffer操作，一点问题也没有
//        origin.writeInt(5);
//        log(origin);
//        log(slice1);
//        log(slice2);

        /**
         * 因为切片在初始化的时候就限定死了，你如果这里进行【插】的动作，
         * 那就会打乱原buffer的顺序（因为物理上是不分离的，会报错）
         */
//        slice1.writeInt(5);

        // setByte可以，是因为这个是一个替换的效果，不会对原buffer进行位置上的改动
        slice1.setByte(1, 9);
        log(slice1);
    }

    public static void log(ByteBuf buffer) {
        int length = buffer.readableBytes();
        int rows = length / 16 + (length % 15 == 0 ? 0 : 1) + 4;
        StringBuilder buf = new StringBuilder(rows * 80 * 2)
                .append("read index:").append(buffer.readerIndex())
                .append(" write index:").append(buffer.writerIndex())
                .append(" capacity:").append(buffer.capacity())
                .append(NEWLINE);
        appendPrettyHexDump(buf, buffer);
        System.out.println(buf.toString());
    }
}
